package com.sgcc.pda.ssal.mqtt;

import android.content.Context;
import android.os.CountDownTimer;
import android.os.SystemClock;

import com.hzwq.codec.client.impl.MQTTOverSSALClient;
import com.hzwq.codec.client.model.SSALServerProperties;
import com.hzwq.codec.config.SSALConfigInitProperties;
import com.hzwq.codec.consts.SSALConst;
import com.sgcc.pda.baselibrary.utils.DeviceUtil;
import com.sgcc.pda.baselibrary.utils.LogUtil;
import com.sgcc.pda.mdrh.app.ZoomApplication;
import com.sgcc.pda.mdrh.log.HzLogSaveUtil;
import com.sgcc.pda.mdrh.task.safelibrary.BuildConfig;
import com.sgcc.pda.sdk.utils.ZoomSPUtils;
import com.sgcc.pda.sdk.utils.db.SharepreferenceUtil;
import com.sgcc.pda.ssal.mqtt.proxy.client.MqttProxyClient;

import org.eclipse.paho.client.mqttv3.MqttClient;
import org.eclipse.paho.client.mqttv3.MqttConnectOptions;
import org.eclipse.paho.client.mqttv3.MqttException;
import org.eclipse.paho.client.mqttv3.persist.MemoryPersistence;

import java.util.UUID;

import static com.sgcc.pda.mdrh.entity.Constants.TOPIC_MESSAGE;
import static com.sgcc.pda.mdrh.entity.Constants.TOPIC_NOTIFICATION;

/**
 * @author zcj
 * @date 2019/9/2
 */
public class MQTTManager {

    private static final String TAG = "mqtt";
    private static MQTTManager instance;
    private MqttClient mqttClient;
    private boolean isConnected = false;

    private MQTTManager() {

//        connect();

    }

    public static MQTTManager getInstance() {
        synchronized (MQTTManager.class) {
            if (instance == null) {
                instance = new MQTTManager();
            }
            return instance;
        }
    }

    /**
     * 订阅主题
     *
     * @param topic 主题
     * @return 是否成功
     */
    public boolean subscribe(String topic) {
        if (mqttClient == null
                || !mqttClient.isConnected()) {
            LogUtil.d(TAG, "subscribe 时 MQTT服务未连接");
            connect();
        }
        try {
            // Qos:(0只发一次，1至少收1次，2只收1次)
            mqttClient.subscribe(topic, 0);
            LogUtil.d(TAG, "subscribe-->topic：" + topic);
            return true;
        } catch (MqttException e) {
            e.printStackTrace();
            LogUtil.e(TAG, "subscribe error: " + e.getMessage());
            return false;
        }
    }

    /**
     * 发布消息方法
     * topic 话题名称
     * content  发布内容
     */
    public boolean publish(String topic, String content) {
        if (mqttClient == null
                || !mqttClient.isConnected()) {
            LogUtil.d(TAG, "publish 时 MQTT服务未连接");
            connect();
        }
        try {
            mqttClient.publish(topic, content.getBytes(), 0, false);
            LogUtil.d(TAG, "publish-->topic：" + topic + ", content：" + content);
            return true;
        } catch (MqttException e) {
            e.printStackTrace();
            LogUtil.e(TAG, "publish error: " + e.getMessage());
            return false;
        }
    }

    /**
     * 取消订阅话题
     * topic 话题名称
     */
    public boolean unsubscribe(String topic) {
        if (mqttClient == null
                || !mqttClient.isConnected()) {
            LogUtil.d(TAG, "unsubscribe 时 未连接");
            connect();
        }
        try {
            mqttClient.unsubscribe(topic);
            LogUtil.d(TAG, "unsubscribe-->topic：" + topic);
            return true;
        } catch (MqttException e) {
            e.printStackTrace();
            LogUtil.e(TAG, "unsubscribe error: " + e.getMessage());
            return false;
        }
    }


    /**
     * 第1步：
     * 连接MQTT服务
     *
     * @return 是否成功
     */
    public synchronized boolean connect() {
        if (mqttClient != null && mqttClient.isConnected()) {
            return true;
        }

        try {
            mqttClient = getMqttClient();
            if (mqttClient == null) return false;

            MqttConnectOptions connectOptions = new MqttConnectOptions();
            connectOptions.setCleanSession(false);
            String ipAddress = DeviceUtil.getIPAddress(ZoomApplication.getInstance());
            String uuid = UUID.randomUUID().toString().replace("-", "");
            connectOptions.setUserName(ipAddress + "-" + uuid);
            connectOptions.setConnectionTimeout(2);
//            connectOptions.setKeepAliveInterval(10);
            this.mqttClient.setCallback(new PahoMqttCallback());
            this.mqttClient.setTimeToWait(2000);
            LogUtil.d(TAG, "开始连接broker。 userName:" + connectOptions.getUserName());

            this.mqttClient.connect(connectOptions);
            LogUtil.d(TAG, "Connected, broker连接成功");
            HzLogSaveUtil.saveLog("Broker连接成功，clinetId==" + mqttClient.getClientId() + " userName==" + connectOptions.getUserName(), HzLogSaveUtil.LogType.MQTT);

            //订阅端到端消息主题 保持跟会话标识一致，不然没办法接收端对端消息
            subscribe(TOPIC_MESSAGE + this.mqttClient.getClientId());
            //连接成功就订阅小红点通知Topic
            subscribe(TOPIC_NOTIFICATION);

            return true;
        } catch (Exception e) {
            e.printStackTrace();
            LogUtil.e(TAG, "连接失败" + e.getMessage());
            return false;
        }
    }

    /**
     * 断开MQTT服务连接
     */
    public void disConnect() {
        if (mqttClient != null && mqttClient.isConnected()) {
            try {
                mqttClient.disconnect();
            } catch (MqttException e) {
                e.printStackTrace();
            }
        }
    }

    private String getIP(Context context) {
        String ip;
        if (SharepreferenceUtil.getCommUsbEnable(context)) {
            ip = SharepreferenceUtil.getCommIpUSB(context);
        } else {
            ip = SharepreferenceUtil.getCommIp(context);
        }
        return ip;
    }

    private int getPort(Context context) {
        String port;
        if (SharepreferenceUtil.getCommUsbEnable(context)) {
            port = SharepreferenceUtil.getCommPortUSB(context);
        } else {
            port = SharepreferenceUtil.getCommPort(context);
        }
        return Integer.parseInt(port);
    }

    /**
     * MQTT服务是否已连接
     *
     * @return 是否连接
     */
    public boolean isConnected() {
        return mqttClient != null && mqttClient.isConnected();
    }

    /**
     * 微应用上线之后，与Broker建立连接
     * 逻辑
     */
    public void login() {
        if (!BuildConfig.ISSSAL) {
            boolean connect = connect();
            LogUtil.e(TAG, "paho连接结果==" + connect);
            return;
        }

        if (!MqttProxyClient.isConnect) {
            ZoomApplication.startProxyClient();
            LogUtil.e(TAG, "代理客户端开始连接...");
        } else {
            LogUtil.e(TAG, "代理客户端已建立连接");
        }

        if (!isConnected()) {
            new CountDownTimer(1000, 1000) {

                @Override
                public void onTick(long millisUntilFinished) {

                }

                @Override
                public void onFinish() {
                    LogUtil.e(TAG, "延迟一秒建立paho连接");
                    if (MqttProxyClient.isConnect) {
                        boolean connect = MQTTManager.getInstance().connect();
                        LogUtil.e(TAG, "paho连接结果==" + connect);
                    } else {
                        //防止一秒内，代理客户端没有连上网关，重试一次
                        LogUtil.e("一秒内没有连上网关，再试一次");
                        SystemClock.sleep(1000);
                        if (MqttProxyClient.isConnect) {
                            boolean connect = MQTTManager.getInstance().connect();
                            LogUtil.e(TAG, "paho连接结果==" + connect);
                        } else {
                            LogUtil.e("两秒后还没连上");
                        }
                    }
                }
            }.start();
        } else {
            LogUtil.e(TAG, "paho已建立连接,不再重新连接");
        }


    }


    /**
     * 微应用登出的时候要断开broker以及代理客户端
     */
    public void logout() {

        LogUtil.e(TAG, "收到登出广播");
        MQTTManager.getInstance().disConnect();

        //退出的时候把代理客户端，主动关闭连接，防止IP地址更换后，无法重新连接apigate。
//        MqttProxyClient.closeConnection();

        new CountDownTimer(1000, 1000) {

            @Override
            public void onTick(long millisUntilFinished) {

            }

            @Override
            public void onFinish() {
                LogUtil.e(TAG, "延迟一秒断开连接");
                try {
                    MqttProxyClient.closeConnection();

                } catch (Exception e) {
                    e.printStackTrace();
                    LogUtil.e("reject崩溃");
                }
            }
        }.start();

    }

    /**
     * 自定义方法获取mqttClient。
     * 根据是否过ssal协议，返回不同的MqttClient
     */
    private MqttClient getMqttClient() {

        try {
            MqttClient mqttClient;
            String yEsamNum = ZoomSPUtils.getYesamNum();
            String ip = getIP(ZoomApplication.getInstance());
            int port = getPort(ZoomApplication.getInstance());


            String imei = DeviceUtil.getDeviceIMEI(ZoomApplication.getInstance());
            String userCode = ZoomSPUtils.getUserCode();
            String clientId = userCode;// 端对端消息会话标识

            LogUtil.d(TAG, "clientId:" + clientId);

            if (BuildConfig.ISSSAL) {
                //过ssal协议，连接本地代理服务netty
                SSALServerProperties ssalServerProperties = new SSALServerProperties.Builder()
                        .setFrontProxyIp(ip)
                        .setFrontProxyPort(port)
                        .setPspMacAddress(yEsamNum)
                        .setMaxFrameLength(SSALConst.MAX_LUD_BYTE_LENGTH)
                        .build();

                String serverURI = SSALConfigInitProperties.MQTT_PROXY_SERVER_URI;
                mqttClient = new MQTTOverSSALClient(ssalServerProperties, serverURI, clientId, new MemoryPersistence());

            } else {
                //不过ssal协议，直接连网关
                String serverURI = "tcp://" + ip + ":" + port;
                mqttClient = new MqttClient(serverURI, clientId, new MemoryPersistence());
                LogUtil.e(TAG, "不过ssal协议直连网关 uri：" + serverURI);
            }
            return mqttClient;
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }


}
